package cn.turboinfo.fuyang.api.domain.mini.usecase.login;

import cn.turboinfo.fuyang.api.domain.common.service.user.*;
import cn.turboinfo.fuyang.api.domain.common.service.wechat.WechatService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.domain.mini.service.session.MiniSessionService;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.LoginCheckType;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.LoginNameType;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.ThirdPartyType;
import cn.turboinfo.fuyang.api.entity.common.fo.wechat.WechatAuthResult;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUser;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUserCreator;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserLogin;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserThirdPartyCreator;
import cn.turboinfo.fuyang.api.entity.mini.pojo.session.MiniSession;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.base.enums.EnableStatus;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import java.util.List;
import java.util.UUID;

/**
 * 用户名密码登录
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniLoginByPasswordUseCase extends AbstractUseCase<MiniLoginByPasswordUseCase.InputData, MiniLoginByPasswordUseCase.OutputData> {

    private final SysUserService sysUserService;

    private final UserTypeRelService userTypeRelService;

    private final MiniSessionService miniSessionService;

    private final UserLoginService userLoginService;

    private final UserCredentialService userCredentialService;

    private final WechatService wechatService;

    private final UserThirdPartyService userThirdPartyService;

    @Override
    protected OutputData doAction(InputData inputData) {
        // 验证登录
        String loginName = inputData.getLoginName();
        // 解密前端加密内容
        String password = userCredentialService.decrypt(inputData.getPassword());

        // 验证登录方式
        // 优先用户名匹配
        List<UserLogin> loginList = userLoginService.findByLoginNameAndLoginNameTypeAndLoginCheckType(loginName, LoginNameType.USERNAME, LoginCheckType.FRONT_CREDENTIAL);
        if (loginList.isEmpty()) {
            // 没有找到用户名用手机号匹配
            loginList = userLoginService.findByLoginNameAndLoginNameTypeAndLoginCheckType(loginName, LoginNameType.PHONE_NUM, LoginCheckType.FRONT_CREDENTIAL);
        }
        Long userId;

        if (loginList.isEmpty()) {
            log.error("用户不存在, 自动创建, loginName={}", loginName);
            // 创建用户
            SysUserCreator.Builder builder = SysUserCreator.builder()
                    .withMobile(loginName)
                    .withUsername(loginName)
                    .withStatus(EnableStatus.ENABLED);
            SysUser sysUser = sysUserService.save(builder.build(), password);

            //创建关联
            userTypeRelService.createConsumerRel(sysUser.getId());

            userId = sysUser.getId();
        } else {
            UserLogin userLogin = loginList.get(0);
            // 凭据ID
            Long credentialId = userLogin.getLoginCheckId();

            // 验证凭据
            if (!userCredentialService.match(credentialId, password)) {
                throw new RuntimeException("登录名或密码不正确");
            }

            userId = userLogin.getUserId();

            // 用户已存在, 检查是否已有消费者关联
            if (!userTypeRelService.hasConsumerRel(userId)) {
                // 创建相应的关联
                userTypeRelService.createConsumerRel(userId);
            }
        }

        // 登录成功后创建 Session
        MiniSession session = MiniSession
                .builder()
                .userId(userId)
                .build();

        String token = UUID.randomUUID().toString();
        miniSessionService.save(token, session);

        try {
            WechatAuthResult result = wechatService.auth(inputData.getAuthCode());
            String openid = result.getOpenid();

            // 从登录方式检查用户是否存在
            List<UserLogin> wechatLoginList = userLoginService.findByLoginNameAndLoginNameType(openid, LoginNameType.THIRD_PARTY);

            if (wechatLoginList.isEmpty()) {
                // 如果没有则创建用户
                UserThirdPartyCreator thirdPartyCreator = UserThirdPartyCreator
                        .builder()
                        .withUserId(userId)
                        .withThirdPartyAccount(openid)
                        .withThirdPartyType(ThirdPartyType.MINI_WECHAT)
                        .build();

                // 绑定微信三方账号
                userThirdPartyService.bindThirdPartyWithLogin(thirdPartyCreator, LoginCheckType.FRONT_THIRD_PARTY);

            }
        } catch (Exception e) {
            log.error("手机号登录 微信授权失败: {}", e.getMessage());
        }

        return OutputData.builder()
                .token(token)
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        @NotEmpty(message = "登录名不能为空")
        private String loginName;

        @NotEmpty(message = "密码不能为空")
        private String password;

        @NotEmpty(message = "微信授权凭证")
        private String authCode;
    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 登录成功的会话令牌
         */
        private String token;

    }
}
